/*
 *  This file is part of WWWPal.
 *
 *  Copyright (C) 2003  Dr. John Punin, Department of Computer Science
 *  Rensselaer Polytechnic Institute
 *
 *  WWWPal is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  WWWPal is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 *  This file is part of WWWPal.
 *
 *  Copyright (C) 2003  Dr. John Punin, Department of Computer Science
 *  Rensselaer Polytechnic Institute
 *
 *  WWWPal is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  WWWPal is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "LOGR_functions.h"
#include "LOGR_gen_pages.h"
#include "LOGR_independent_pages.h"
#include "LOGR_independent_links.h"
#include "LOGR_gen_links.h"
#include "LOGR_paths.h"
#include "LOGR_country_codes.h"

#include <signal.h>
#include <setjmp.h>

int linkSort (const void *a, const void *b);

extern WebIndependentPagePtr
find_independent_page_in_list(LNode_type *lindependent_pages, char *url);

char *
LOGR_parse_current_directory(char *filename)
{
  if(filename[0]!='/')
    return NULL;
  else
    {
      int i, len=strlen(filename);
      char *wodir;
      for(i=len ; i>=0; i--)
	{
	  if(filename[i]=='/')
	    break;
	}
      wodir = malloc(i+2);
      if(!wodir) {
	  fprintf(stderr,"Out of Memory parse_current_directory\n");
	  abort();
      }
      strncpy(wodir, filename, i+1);
      wodir[i+1]='\0';
      return wodir;
    }
  return NULL;
}


char *
LOGR_complete_filename(char *base_filename, char *rel_filename)
{
  if(base_filename[0] != '/' || rel_filename[0] == '/')
  {
    char * fname = NULL;
    GRStrAllocCopy(fname,rel_filename);
    return fname;
  }
  else
    {
      char *wdir = LOGR_parse_current_directory(base_filename);
      char *filen = malloc(strlen(wdir)+strlen(rel_filename)+2);
      if(!filen) {
	  fprintf(stderr,"Out of Memory complete_filename\n");
	  abort();
      }
      strcpy(filen,wdir);
      strcat(filen,rel_filename);
      free(wdir); wdir = NULL;
      return filen;
    }
  return NULL;
}

void
HTMime_init()
{
  HTBind_init();
  HTFileInit();
  HTBind_addType("class","application/x-java-vm",1.0);
  HTBind_addType("ser","application/x-java-serialized-object",1.0);
  HTBind_addType("jar","application/x-java-archive",1.0);
  HTBind_addType("css","text/css",1.0);
}

char *
HTGetMime(char *url)
{
  BOOL status = NO;
  char *mime = NULL;
  HTFormat format = NULL;
  HTEncoding encoding = NULL;
  HTEncoding transfer = NULL;
  HTLanguage language = NULL;
  double quality=1.0;

  if(!url)
      return NULL;

  status = HTBind_getFormat(url, &format, &encoding, &transfer, &language, 
			    &quality);
/*  if(status)
    GRStrAllocCopy(mime,HTAtom_name(format));*/


  if(status)
  {
      mime = (char *)HTAtom_name(format);
      /*printf("mime %s URL <%s> \n", mime,url);*/
  }

  return mime;
}

void
HTMime_deleteAll()
{
  HTBind_deleteAll();
}

short
LOGR_is_object(char *url)
{
    char *mime = HTGetMime(url);

    if(!strcmp(mime,"image/gif") || !strcmp(mime,"image/jpeg"))
	return 1;
    if(!strcmp(mime,"text/css"))
	return 1;
    if(!strcmp(mime,"image/x-xbitmap"))
	return 1;
    return 0;

}

short
LOGR_is_url_has_suffix(char *urls)
{
    char *p = urls;
    p = urls ? strrchr(urls,'/') : NULL;
    p = p ? strchr(p,'.') : NULL;
    return (p ? 1 : 0);
}

TypeEdgeReferer
LOGR_type_edge_referer(WebStatPtr wsn,char *uri)
{
    const char *base_webhost = NULL;
    
    if(!uri || !wsn)
	return 0;
    
    base_webhost = LOGR_get_base_webhost(wsn);
    if(strncmp(uri,base_webhost, strlen(base_webhost)))
	return EXTERNAL_REFERER;

    return INTERNAL_REFERER;
    
}

TypeReferer
LOGR_type_url(char *url)
{
    if(!url)
	return 0;

    if(strchr(url,'?'))	
	return RDYNAMIC_REF;
    else
	return RSTATIC_REF;
    
    return 0;
}

short
LOGR_is_url_non_html(char *url)
{
  char *mime = HTGetMime(url);
  if(!url)
      return 1;
  if(!strcmp(mime,"text/html"))
      return 0;
  else if(!strcmp(mime,"www/unknown"))
  {
      return (LOGR_is_url_has_suffix(url));
  }
  return 1;
}

HTAssocList *
HTParse_query(char *url)
{
    char *p, *a, *e,*z = NULL;
    const char *name = NULL;
    const char *value = NULL;
    HTChunk *chname = NULL;
    HTChunk *chvalue = NULL;
    HTAssocList *al = NULL;
    if(!url)
	return NULL;
    p = strchr(url,'?');
    if(!p)
	return NULL;

    p++;
    while(*p=='&')
	p++;
    
    z = strchr(url,'\0');

    chname = HTChunk_new(128);
    chvalue = HTChunk_new(128);
    al = HTAssocList_new();

    do {
	e = strchr(p,'=');
	a = strchr(p,'&');
	if(e && ((a > e) || !a)) {
	    HTChunk_putb(chname, p,(int)(e-p));
	    if(a)
		HTChunk_putb(chvalue, e+1,(int)(a-e-1));
	    else
		HTChunk_putb(chvalue, e+1,(int)(z-e-1));
	    name = HTChunk_data(chname); 
	    value = HTChunk_data(chvalue); 
	    if(name && value)
	    {
		/*printf("\tName %s, value %s\n", name, value);*/
		HTAssocList_addObject(al,name,value);
	    }
	    HTChunk_clear(chname);
	    HTChunk_clear(chvalue);
	}
	p = a+1;
    } while(a);
    return al;
}



SearchEngineType 
LOGR_get_search_engine_type(char *url)
{
  char *host= NULL;
  if(!url)
      return 0;

  host = HTParse(url,"",PARSE_HOST);

  if(!strcmp(host,SALTAVISTA))
      return TALTAVISTA;

  if(!strcmp(host,SYAHOO))
      return TYAHOO;

  if(!strcmp(host,SYAHOO2))
      return TYAHOO2;

  if(!strcmp(host,SGOOGLE))
      return TGOOGLE;

  if(!strcmp(host,SGOOGLE2))
      return TGOOGLE2;

  if(!strcmp(host,SINFOSEEK))
      return TINFOSEEK;

  if(!strcmp(host,SLYCOS))
      return TLYCOS;

  if(!strcmp(host,SLYCOS2))
      return TLYCOS2;
  
  if(!strcmp(host,SHOTBOT))
      return THOTBOT;

  if(!strcmp(host,SHOTBOT2))
      return THOTBOT2;  

  return 0;
}

void
LOGR_string_tolower(char *str)
{
    char *p = NULL;
    if(!str)
	return;
    p = str;
    while(*p != '\0')
    {
	*p = tolower(*p);
	p++;
    }
}

/*
**	Parse a str in Apache date format to a local time time_t representation
**	The format is accepted:
**
**              day/month/year:hour:minute:second zone
*/

static char * months[12] = {
    "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};

char *
LOGR_string_month(int month)
{
    if(month < 0 && month > 11)
	return NULL;
    return (char *)months[month];
}

int make_month (char * s, char ** ends)
{
    char * ptr = s;
    while (!isalpha((int) *ptr)) ptr++;
    if (*ptr) {
	int i;
	*ends = ptr+3;		
	for (i=0; i<12; i++)
	    if (!strncasecomp(months[i], ptr, 3)) return i;
    }
    return 0;
}

PUBLIC char *
HTStringTimeApache (time_t t)
{
    char *sdate = NULL;
    char buffer[100];
    if(t)
    {
	strftime(buffer,100,"%d/%b/%Y:%X",localtime(&t));
	GRStrAllocCopy(sdate,buffer);
    }
    return sdate;
}

void
HTBufferTimeApache (time_t t, char *buffer, int n)
{
    if(t && buffer)
	strftime(buffer,n,"%d/%b/%Y:%X",localtime(&t));
}


PUBLIC time_t HTParseTimeApache (const char * str)
{
    char * s;
    struct tm tm;
    time_t t;

    if (!str) return 0;

    s = (char *)str;

    if (strchr(s,'/')) {
	/*fprintf(stderr, "Format...... 00/Mon/0000:00:00:00 zone\n");*/
	if ((int)strlen(s) < 26) {
	   fprintf(stderr, "ERROR....... Not a valid time format \"%s\"\n",s);
		return 0;
	    }
	tm.tm_mday = strtol(s, &s, 10);
	tm.tm_mon = make_month(s, &s);
	tm.tm_year = strtol(++s, &s, 10)-1900;
	tm.tm_hour = strtol(++s, &s, 10);
	tm.tm_min = strtol(++s, &s, 10);
	tm.tm_sec = strtol(++s, &s, 10);	
	tm.tm_wday = 0;
	tm.tm_yday = 0;
	tm.tm_isdst = -1;
    }
    /*{
	char str[100];
	strftime(str,100,"%H:%M:%S on %A, %d %B %Y", &tm);
	printf("New Date %s\n",str);
	}*/

#ifdef HAVE_MKTIME
    t = mktime(&tm);
#else
#ifdef HAVE_TIMEGM
    t = timegm(&tm);
#else
#error "Neither mktime nor timegm defined"
#endif /* HAVE_TIMEGM */
#endif /* HAVE_MKTIME */
 
    return t;
}

char *
LOGR_gen_string_id(char *urls, char *urlt)
{
  HTChunk *chid = NULL;

  if(!urls || !urlt)
      return NULL;

  chid = HTChunk_new(128);

  HTChunk_puts(chid,urls);
  HTChunk_putc(chid,'-');
  HTChunk_puts(chid,urlt);

  return HTChunk_toCString(chid);
}

char *
LOGR_gen_link_id(TypePage tps, void *nodeptrs, 
		 TypePage tpt, void *nodeptrt)
{
  char *urls, *urlt = NULL;
  if(!nodeptrs || !nodeptrt) return NULL;

  urls = (char *)LOGR_get_local_node_url(tps,nodeptrs);
  urlt = (char *)LOGR_get_local_node_url(tpt,nodeptrt);

  return LOGR_gen_string_id(urls, urlt);

}

WebGenLinkPtr
find_gen_link_in_graph_array(void *GArray,char *urls, char *urlt)
{
    HTArray *garray = (HTArray *)GArray;
    int i;

    if(!GArray || !urls || !urlt)
	return NULL;

    for (i = 0; i < HTArray_size(garray); i++)
    {
        WebGenLinkPtr link = (WebGenLinkPtr)(HTArray_data(garray)[i]);
	if(LOGR_is_gen_link_name(link,urls,urlt))
	    return link;
    }
    return NULL;
}

int 
linkSort (const void *a, const void *b)
{
    char *aurls = (char *)LOGR_get_gen_url_source((WebGenLinkPtr)a);
    char *aurlt = (char *)LOGR_get_gen_url_target((WebGenLinkPtr)a);
    char *burls = (char *)LOGR_get_gen_url_source((WebGenLinkPtr)b);
    char *burlt = (char *)LOGR_get_gen_url_target((WebGenLinkPtr)b);
    char *asid = LOGR_gen_string_id(aurls, aurlt);
    char *bsid = LOGR_gen_string_id(burls, burlt);
    return strcmp(asid?asid:"", bsid?bsid:"");
}

void 
LOGR_sort_graph_edges(void *GArray)
{
    HTComparer *comp = NULL;

    comp = (HTComparer *)linkSort;

    HTArray_sort(GArray, comp);
}

short
LOGR_is_graphs_equal(void *GArray,void *HArray)
{
    HTArray *garray = (HTArray *)GArray;
    HTArray *harray = (HTArray *)HArray;
    int sg= HTArray_size(garray);
    int sh= HTArray_size(harray);
    int i;
    
    if(sg != sh)
	return 0;
    
    for (i = 0; i < sg; i++)
    {
        WebGenLinkPtr glink = (WebGenLinkPtr)(HTArray_data(garray)[i]);
        WebGenLinkPtr hlink = (WebGenLinkPtr)(HTArray_data(harray)[i]);
	if(!LOGR_is_gen_links_equal(glink,hlink))
	    return 0;
    }
    return 1;
}

WebGenLinkPtr 
LOGR_add_edge_graph(void *GArray,char *urls, char *urlt,
		    WebStatPtr wsf,GraphFrame *gf)
{
    WebGenLinkPtr gln = NULL;
    HTArray *garray = (HTArray *)GArray;

    if(!GArray || !urls || !urlt || !wsf || !gf)
	return NULL;
    
    gln = find_gen_link_in_graph_array(GArray,urls,urlt);

    if(!gln)
    {
	gln = new_web_gen_link();
	LOGR_set_gen_link_from_name(gln, urls, urlt, wsf,gf);
	HTArray_addObject(garray, (void *) gln);
    }

    return gln;
}

void
LOGR_add_edge_to_path_from_graph(WebPathPtr upn,char *urls, char *urlt,
				 void *GArray)
{
    WebGenLinkPtr gln = NULL;

    if(!GArray || !urls || !urlt || !upn)
	return;
    
    gln = find_gen_link_in_graph_array(GArray,urls,urlt);

    if(!gln)
	fprintf(stderr,"Edge is not in graph %s - %s\n",urls,urlt);
    else
	LOGR_add_path_edge(upn,gln);

}

void *
init_graph_array()
{
    HTArray *garray = HTArray_new(128);
    return (void *) garray;
}

void
delete_graph_array(void *GArray)
{
    HTArray *garray = (HTArray *)GArray;
    if(!garray)
	return;
    HTArray_delete(garray);

}

int 
LOGR_get_number_edges(void *GArray)
{
    HTArray *garray = (HTArray *)GArray;
    int sg = 0;
    if(!garray)
	return 0;
    sg= HTArray_size(garray);

    return sg;
}

WebGenLinkPtr
LOGR_get_gen_edge_i(void *GArray,int i)
{
    HTArray *garray = (HTArray *)GArray;
    WebGenLinkPtr glink = NULL;
    int sg = 0;
    if(!garray)
	return NULL;
    sg= HTArray_size(garray);

    if(i<0 && i>=sg)
	return NULL;
    glink = (WebGenLinkPtr)(HTArray_data(garray)[i]);
    return glink;
}

void *
init_current_users()
{
    HTList *clist = HTList_new();
    return (void *)clist;
}

void
delete_list_current_users(void *lcusers)
{
    HTList * cur = (HTList *)lcusers;
    WebUserPtr pres;
    if(!lcusers)
	return;
    while ((pres = (WebUserPtr) HTList_nextObject(cur))) {
	delete_web_user_node(pres);
    }
    HTList_delete(cur);
}

void *
find_user_in_list_current_users(void *lcusers, char *nuser)
{
    HTList * cur = (HTList *)lcusers;
    WebUserPtr pres;
    if(!lcusers || !nuser)
	return NULL;
    while ((pres = (WebUserPtr) HTList_nextObject(cur))) {
	char *uname = LOGR_get_user_name(pres);
	if(pres && uname && !strcmp(uname,nuser))
	    return pres;
    }
    return NULL;
}

void 
add_user_to_list_current_users(void *lcusers, WebUserPtr usn)
{
    HTList * cur = (HTList *)lcusers;
    if(!lcusers || !usn)
	return;
    HTList_addObject(cur, (void *)usn);
}

const char *
LOGR_get_url_title(GraphFrame *gf,char *url)
{
    PNODE v = NULL;
    if(!gf || !url)	
	return NULL;
    v = find_vertex_by_name(gf,url);
    return(v ? get_attribute(v,"title") : NULL);
}

char *
LOGR_get_xml_string(char *str)
{
    char *p = str;
    char *rstr = NULL;
    HTChunk *buf = HTChunk_new(64);
    while(*p != '\0')
    {
	if(*p == '<')
	    HTChunk_puts(buf,"&lt;");
	else if(*p == '>')
	    HTChunk_puts(buf,"&gt;");
	else if(*p == '&')
	    HTChunk_puts(buf,"&amp;");
	else if(*p == '"')
	    HTChunk_puts(buf,"&quot;");
	else
	    HTChunk_putc(buf,*p);
	p++;
    }

    rstr = HTChunk_toCString(buf);
    return rstr;
}


const char *
LOGR_get_string_code(int code)
{
    if(code == 200)
	return S200;
    else if(code == 206)
	return S206;
    else if(code == 301)
	return S301;
    else if(code == 302)
	return S302;
    else if(code == 304)
	return S304;
    else if(code == 400)
	return S400;
    else if(code == 401)
	return S401;
    else if(code == 402)
	return S402;
    else if(code == 403)
	return S403;
    else if(code == 404)
	return S404;
    else if(code == 405)
	return S405;
    else if(code == 408)
	return S408;
    else if(code == 500)
	return S500;
    else if(code == 501)
	return S501;
    else
	return NULL;
}

const char *
LOGR_get_string_method(int method)
{
    if(method == HTTP_METHOD_UNKNOWN)
	return SMUNKNOWN;
    else if(method == HTTP_METHOD_GET)
	return SMGET;
    else if(method == HTTP_METHOD_HEAD)
	return SMHEAD;
    else if(method == HTTP_METHOD_POST)
	return SMPOST;
    else if(method == HTTP_METHOD_PUT)
	return SMPUT;
    else if(method == HTTP_METHOD_OPTIONS)
	return SMOPTIONS;
    else if(method == HTTP_METHOD_DELETE)
	return SMDELETE;
    else if(method == HTTP_METHOD_TRACE)
	return SMTRACE;
    else
	return SMUNKNOWN;
}

const char *
LOGR_get_string_version(int version)
{
    if(version == HTTP_VERSION_UNKNOWN)
	return SVUNKNOWN;
    else if(version == HTTP_VERSION_10)
	return SV10;
    else if(version == HTTP_VERSION_11)
	return SV11;
    else
	return SVUNKNOWN;
}

const char *
LOGR_get_token_version(int version)
{
    if(version == HTTP_VERSION_UNKNOWN)
	return TVUNKNOWN;
    else if(version == HTTP_VERSION_10)
	return TV10;
    else if(version == HTTP_VERSION_11)
	return TV11;
    else
	return TVUNKNOWN;
}


char *
LOGR_get_xml_escape_string(char *str)
{
    if(!str)
	return NULL;
    return HTEscape(str,URL_XALPHAS);

}

#define HEX_ESCAPE '%'
#define ROB_ACCEPTABLE(a)	( a>=32 && a<128 )

PRIVATE char *hex = "0123456789ABCDEF";

PRIVATE char *
HTEscape_p_nonascii(const char * str)
{
    const char * p;
    char * q;
    char * result;
    int unacceptable = 0;
    if (!str) return NULL;
    for(p=str; *p; p++)
        if (!ROB_ACCEPTABLE((unsigned char)TOASCII(*p)))
		unacceptable++;
    if ((result = (char  *) HT_MALLOC(p-str + unacceptable+ unacceptable + 1)) == NULL)
        HT_OUTOFMEM("HTEscape_nonascii");
    for(q=result, p=str; *p; p++) {
    	unsigned char a = TOASCII(*p);
	if (!ROB_ACCEPTABLE(a)) {
	    *q++ = HEX_ESCAPE;	/* Means hex commming */
	    *q++ = hex[a >> 4];
	    *q++ = hex[a & 15];
	}
	else *q++ = *p;
    }
    *q++ = 0;			/* Terminate */
    return result;
}

char *
LOGR_get_xml_escape_nonascii_string(char *str)
{
    if(!str)
	return NULL;
    return HTEscape_p_nonascii(str);
}

char *
LOGR_get_xml_nescape_string(char *str)
{
    char *rstr = NULL;
    char *xstr = NULL;
    if(!str)
	return NULL;
    rstr = LOGR_get_xml_escape_nonascii_string(str);
    xstr = LOGR_get_xml_string(rstr);
    if(rstr) {
	free(rstr); rstr = NULL;
    }
    return xstr;
}	
void
LOGR_to_lower(char *str)
{
    char *ptr = str;
    if(!ptr)
	return;
    while(*ptr!='\0') 
    {
	*ptr = tolower(*ptr);	
	ptr++;
    }	
}

/* given a string holding a hostname, convert to a dotted-decimal
   IP address (a string holding a dotted-decimal address)
   Thanks to Dave Hollinger
*/

char *
LOGR_IPfromhost( char *hostname ) 
{
  struct hostent *ho = NULL;
  char *IP = NULL;
  char *hname = NULL;
  struct in_addr addr;

  /* call gethostbyname to get the full record for this host */
  ho = gethostbyname(hostname);

  /* if gethostbyname returns null - the DNS lookup failed 
     (no such host or DNS is down)
  */
  if (ho==NULL)
    return(NULL);

  /* grab the IP address only (the first one) */
  memcpy(&addr,ho->h_addr_list[0],4);


  /* convert the IP address to dotted decimal */
  hname = inet_ntoa(addr);

  GRStrAllocCopy(IP,hname);

  return(IP);
}

static sigjmp_buf	jmpbuf;

char *
LOGR_hostfromIP( char *ip ,int timeout) 
{
  struct hostent *ho = NULL;
  char *hostname = NULL;
  int addr = 0;


  /* first convert the string holding a dotted-decimal IP address to 
     a network-byte-order binary IP address */
  if ((addr = inet_addr(ip)) == -1)
    return(NULL);  /* no address converted ! */

  /* now call gethostbyaddr to ask DNS for the (canonical) name 
     corresponding to this address */

  /* set up for a long jump from the alarm interrupt handler */
  if (sigsetjmp(jmpbuf,1)==0) {

      /* Set up for an alarm in 5 seconds */
     alarm(timeout);
     ho = gethostbyaddr((char *)&addr,sizeof(int),AF_INET);
     alarm(0);
  }

  /* if gethostbyaddr return null it didn't find anything ! */
  if (ho==NULL)
    return(NULL);

  GRStrAllocCopy(hostname,ho->h_name);

  return(hostname);
}

void 
alrm_handler(int x) 
{
  signal(x, SIG_IGN);
  write(2,".",1);
  /*write(2,"ALARM - timed out\n",20);*/
  signal(SIGALRM,alrm_handler);

  siglongjmp(jmpbuf,1);   /* long jump to just before call to gethostbyaddr */
}

char *
LOGR_hostfromIP_simple( char *ip ) 
{
  struct hostent *ho = NULL;
  char *hostname = NULL;
  int addr = 0;

  /* first convert the string holding a dotted-decimal IP address to 
     a network-byte-order binary IP address */
  if ((addr = inet_addr(ip)) == -1)
    return(NULL);  /* no address converted ! */

  /* now call gethostbyaddr to ask DNS for the (canonical) name 
     corresponding to this address */

  ho = gethostbyaddr((char *)&addr,sizeof(int),AF_INET);

  /* if gethostbyaddr return null it didn't find anything ! */
  if (ho==NULL)
    return(NULL);

  GRStrAllocCopy(hostname,ho->h_name);

  return(hostname);
}

/*
short
LOGR_is_ip(char *str)
{
    return (str && isdigit((int)str[0]) && isdigit((int)str[strlen(str)-1]));
}
*/

short
LOGR_is_ip(char *str)
{
    ulong_t addr = str ? inet_addr(str) : (ulong_t) -1;
    return((int)addr != -1);
}

char *
LOGR_get_long_country_code(char *code)
{
    int i = 0;

    if(!code)
	return NULL;

    for(i = 0; i< COUNTRY_CODES*2; i+=2)
    {
	if(!strcmp(code,country_codes[i]))
	    return country_codes[i+1];
    }
    return NULL;
}

short
LOGR_is_address_local(WebStatPtr wsf,char *address)
{
    short isip = 0;
    char *ldomain = NULL;
    char *p = NULL;
    int lld = 0;
    int lad = 0;
    if(!wsf || !address)
	return 0;
    lad = strlen(address);
    isip = LOGR_is_ip(address);
    ldomain = (char *)LOGR_get_local_domain(wsf);
    if(ldomain)
	lld = strlen(ldomain);  

    if(isip)
    {
	return(LOGR_is_ip_local(wsf,address));
    }
    else
    {
	if(lad < lld)
	    return 0;
	p = &(address[lad-lld]);
	return(!strcmp(ldomain,p));
    }
    return 0;
}

short
LOGR_is_address_in_subnet( char *addr, char *subnet, int plen) 
{

  int i;
  unsigned long mask=0;

  struct in_addr b_addr,b_subnet;

  b_addr.s_addr=inet_addr(addr);
  b_subnet.s_addr = inet_addr(subnet);

  for (i=0;i<plen;i++) {
    mask |= (0x80000000>>i);
  }

  b_addr.s_addr = htonl( ntohl(b_addr.s_addr) & mask);
  b_subnet.s_addr = htonl( ntohl(b_subnet.s_addr) & mask);

  return (b_addr.s_addr == b_subnet.s_addr);
}

void
delete_list_strings(LNode_type *llist)
{
  LNode_type *ptr = NULL;

  if(!llist) return;

  for(ptr = llist->back ; ptr != llist ; ptr = ptr->back)
  {
    char *str = (char *)ptr->info; 
    free(str); str = NULL;
  }
  Delete_all_list(llist); 
}



HttpMethodType
LOGR_get_http_method_type(char *method)
{
    if(!method)
	return HTTP_METHOD_UNKNOWN;

    if(!strcmp(method, "GET"))
	return HTTP_METHOD_GET;
    else if(!strcmp(method, "HEAD"))
	return HTTP_METHOD_HEAD;
    else if(!strcmp(method, "POST"))
	return HTTP_METHOD_POST;
    else if(!strcmp(method, "PUT"))
	return HTTP_METHOD_PUT;
    else if(!strcmp(method, "OPTIONS"))
	return HTTP_METHOD_OPTIONS;
    else if(!strcmp(method, "DELETE"))
	return HTTP_METHOD_DELETE;
    else if(!strcmp(method, "TRACE"))
	return HTTP_METHOD_TRACE;
    else
	return HTTP_METHOD_UNKNOWN;
}

HttpVersionType
LOGR_get_http_version_type(char *version)
{
    if(!version)
	return HTTP_VERSION_UNKNOWN;

    if(!strcmp(version, "HTTP/1.0"))
	return HTTP_VERSION_10;
    else if(!strcmp(version, "HTTP/1.1"))
	return HTTP_VERSION_11;
    else
	return HTTP_VERSION_UNKNOWN;
}

char *
find_label_in_pages(WebStatPtr wsf, GraphFrame *gf, char *uri)
{
    PNODE v = gf ? find_vertex_by_name(gf, uri) : NULL;
    WebIndependentPagePtr wip = NULL;
    if(v)
	return get_label_vertex(v);

    wip = find_independent_page_in_list(wsf->independent_pages,uri);
    if(wip)
	return (char *)LOGR_get_ip_url(wip);
    return NULL;
}

char *
LOGR_get_absolute_uri(WebStatPtr wsf, GraphFrame *gf,char *uri,const char *base_webhost, int *new)
{
    char * auri = NULL;
    char * nuri = NULL;
    *new = 0;
    auri = get_element_hashed(wsf->labels,uri);
    if(!auri)
    {
	auri = HTParse(HTUnEscape(uri), base_webhost, PARSE_ALL);
	HTSimplify(&auri);
	nuri = find_label_in_pages(wsf,gf,auri);
	if(nuri)
	{
	    /*printf("FOUND IN GRAPHS <%s> - %s \n",uri,nuri);*/
	    insert_hash_info(wsf->labels, uri, nuri);  
	}
	*new = 1;
    }
    else
    {
	/*printf("FOUND IN LABELS <%s> - %s\n",uri,auri);*/
    }
    return auri;
}

char *
LOGR_get_absolute_uri2(WebStatPtr wsf, char *uri,const char *base_webhost, int *new)
{
    char * auri = NULL;
    *new = 0;
    auri = HTParse(HTUnEscape(uri), base_webhost, PARSE_ALL);
    HTSimplify(&auri);
    *new = 1;
    return auri;
}

